import ShapeEditorComponent from '@/components/ShapeEditor.vue';
import { h, createApp, App } from 'vue';
import Event from './Event';

interface ShapeEditorEvents {
  [ShapeEditor.EVENT_SAVE]: (rawDatas: Array<Editor.CropPlotRawData>) => void;
  [ShapeEditor.EVENT_CLOSE]: () => void;
}

/**
 * ShapeEditor 类下持有一个 Vue APP
 * Vue APP close 时，只销毁了 Vue APP，并没有销毁 ShapeEditor
 */
export default class ShapeEditor extends Event<ShapeEditorEvents> {
  static EVENT_SAVE = 'SHAPE_EDITOR_SAVE';
  static EVENT_CLOSE = 'SHAPE_EDITOR_CLOSE';

  /**
   * 编辑器选项
   */
  option: Editor.ShapeEditorOption = {
    building: undefined,
    preloadRawDatas: [],
  };

  /**
   * 构造函数
   * @param shapeEditorOption - 编辑器选项
   */
  constructor(shapeEditorOption: Editor.ShapeEditorOption) {
    super();
    this.option = shapeEditorOption;
    this.createShapeEditorVueAPP();
  }

  /**
   * 创建 ShapeEditor Vue 应用
   * @returns 包含元素和 Vue 实例的对象
   */
  createShapeEditorVueAPP(): { element: HTMLElement; vm: any } {
    const { building, preloadRawDatas = [] } = this.option;
    const element = document.createElement('div');
    element.style.pointerEvents = 'auto';
    element.setAttribute('id', 'shape-editor');

    let app: App = null;

    // 获取 building 的数据
    const { size } = building.getInfo();

    const _dataCard = h(ShapeEditorComponent, {
      // 传入 asprectRatio 相关参数
      originX: size.x,
      originY: size.y,
      originZ: size.z,
      preloadRawDatas,
      onClose: () => {
        this._emitEvent(ShapeEditor.EVENT_CLOSE, undefined);
        app && app.unmount();
      },
      onSave: (rawDatas: Array<Editor.CropPlotRawData>) => {
        this.handleSave(rawDatas);
        app && app.unmount();
      },
    });

    app = createApp(_dataCard);
    const vm = app.mount(element);
    return { element, vm };
  }

  /**
   * 处理保存事件
   * @param rawDatas - 原始数据
   * @returns 渲染数据
   */
  handleSave(rawDatas: Array<Editor.CropPlotRawData>) {
    // 不在这里转换，提升到plantAreaManager中
    this._emitEvent(ShapeEditor.EVENT_SAVE, rawDatas);
  }

  /**
   * 销毁实例
   */
  destroy(): void {
    this._removeEvents();
    this.option = null;
  }
}
